1. Field of the Invention
This invention is related to the field of digital circuits and, more particularly, to crossing clock boundaries in digital circuits.
2. Description of the Related Art
Electronic systems often have two or more different clock domains, corresponding to different clock signals used in the system. The clock signals that form different clock domains may have different sources, and thus a phase relationship between the clock signals may not be known. The clock signals may have different frequencies. In some cases, the clock signals may have both different sources and different frequencies. Different clock domains may exist on a single integrated circuit, between integrated circuits in a system, or both.
Generally, transmitting data across clock domain boundaries requires some sort of synchronization to ensure that data is safely and accurately captured in the receiving clock domain. First-in, first-out buffers (or more briefly, FIFOs) are frequently used to transfer data between clock domains. The transmitting clock domain writes data into the buffer using a write pointer. Subsequently, after the data is known to be stable in the FIFO, the receiving clock domain reads data from the FIFO. To prevent overrun when the FIFO is full, and to prevent underrun with the FIFO is empty, the FIFO control logic generates empty and full signals. The full signal is generated in the transmitting clock domain, and the empty signal is generated in the receiving clock domain. Typically, the full and empty signals are generated by comparing the read and write pointers. Similarly, detecting that there is data to be read from the buffer may be performed by comparing the read and write pointers. However, to compare the pointers, they must be transmitted between the clock domains.
To transfer pointers between the clock domains, the pointers can be gray-coded (in which at most one bit changes state between consecutive values). While gray-coding is relatively simple for a single pointer pair (read and write), it is far more complicated and difficult if the FIFO is divided into sections for different types of data. The pointers may begin and end on arbitrary boundaries in such a configuration. Moreover, if the size of the sections is programmable, the range of each pointer may be unpredictable until the programming occurs. Gray-coding such pointers would be extremely difficult, if not impossible.
In another mechanism, the pointers are transmitted between the clock domains by dual-rank synchronizing the pointers (also referred to herein as double synchronizing the pointers). A pair of clocked storage devices are coupled in series, in the clock domain that receives a pointer. An input to the series connection receives the pointer from the other clock domain. After passing through the series connection, the pointer is considered stable in the receiving clock domain and can be compared.
Double synchronizing is used to avoid metastability problems that may occur if setup/hold times are violated by a transition in the value of the pointer that is generated in the other clock domain. When such violations occur, the value captured by the clocked storage device may oscillate or an unpredictable value may be captured. Unfortunately, double synchronizing also introduces a two clock cycle latency in the clock domain to which the synchronization is performed. Additionally, at least one extra copy of the pointers is required as they pass through the double synchronization (assuming the second device in the synchronizer is directly used in the receiving clock domain). If there are numerous pointers, the hardware cost of the synchronization is large.